/**
 * @name 加减乘除运算
 * @author wangsongle
 * @description 2021/10/26
 * @copyright http://songle.wang
 * @version 1.0
 */
function accAdd(...val) {
    let max = 0
    let count = 0
    for (let i = 0; i < val.length; i++) {
        const strVal = val[i].toString()
        const index = strVal.indexOf('.')
        let num = 0
        if (index > -1) {
            num = strVal.length - 1 - index
            max = num > max ? num : max
        }
    }
    for (let i = 0; i < val.length; i++) {
        count += Math.round(val[i] * Math.pow(10, max))
    }
    return count / Math.pow(10, max)
}
Number.prototype.add = function(arg){
	return accAdd(arg, this);
}

/**
 * 减法运算
 * @param {Number} num 
 */
function getDecimalLength(num) {
    const decimalStr = num.toString().split('.')[1];
    return decimalStr ? decimalStr.length : 0;
}
function safeSubtract(a, b, precision = 2) {
    const factor = 10 ** Math.max(getDecimalLength(a), getDecimalLength(b), precision);
    return (Math.round(a * factor) - Math.round(b * factor)) / factor;
}
Number.prototype.sub = function(arg, precision = 2){
	return safeSubtract(this, arg, precision);
}

/**
 * @category 乘法运算
 * @param arg1
 * @param arg2
 * @returns
 */
function accMul(...val) {
    const strVal = val[0].toString()
    const strValTwo = val[1].toString()
    const index = strVal.indexOf('.')
    const indexTwo = strValTwo.indexOf('.')
    const num = [0, 0]
    if (index > -1) {
        num[0] = strVal.length - 1 - index
    }
    if (indexTwo > -1) {
        num[1] = strValTwo.length - 1 - index
    }
    return Math.round((val[0] * Math.pow(10, num[0])) * (val[1] * Math.pow(10, num[1]))) / Math.pow(10, num[0] + num[1])
}
Number.prototype.mul = function(arg){
	return accMul(arg, this);
}

/**
 * 除法运算，自定义精度
 * @param {Number} a 
 * @param {Number} b 
 * @param {int} precision 
 */
function divide(a, b, precision = 2) {
    const factor = 10 ** precision
    return Math.round((a / b) * factor) / factor
}
Number.prototype.div = function(arg, precision = 2){
	return divide(this, arg, precision);
}